#ifndef _PDTCODEGRAPG_H_
#define _PDTCODEGRAPG_H_

#include <string>
#include <vector>
#include "PDTNodeDefs.h"
using namespace std;

//#define LEFT 0
//#define RIGHT 1
//:% s/class \([^; {:]*\).*/\1_Em,

class PDTVar;
class PDTConst;
class PDTProp;
class PDTFunctionDec;

class PDTNode;

//#define INPUT_STREAM_DETAILS

#define SETIStremDetails(tok,node) \
    cg->setIStreamDetails(node, $tok.line, $tok.pos, \
            $tok.start, $tok.end);

class PDTCodeGraph {
#ifdef INPUT_STREAM_DETAILS
    class IStreamDetails {public:
    // the following is information that we can get from antlr
    // The line number in the input stream
    // ANTLR3_UINT32   line;
    unsigned int line;  

    // the position of this token on the line
    // ANTLR3_INT32    charPosition;
    unsigned int pos;

    //What the index of this token is, 0, 1, .., n-2, n-1 tokens
    // ANTLR3_MARKER   index;

    // The start and end offsets of this token in the input stream
    // ANTLR3_MARKER   starti,end;
    unsigned int start;  
    unsigned int end; 
    IStreamDetails(unsigned int aline, unsigned int apos,
            unsigned int astart,  unsigned int aend) : 
        line(aline), pos(apos), start(astart), end(aend) {
    };
#endif
public:
	vector <PDTNode*> nodes; //vector containing the id's of the nodes
	vector <PDTVar*> variables;
	vector <PDTConst*> constants;
	vector <PDTProp*> properties;

	NodeId currentId;
	unsigned int maxWhileDepth;


#ifdef INPUT_STREAM_DETAILS
    vector <IStreamDetails> d;
    void setIStreamDetails(PDTNode & node, 
            unsigned int line, unsigned int pos,
            unsigned int start,  unsigned int end) {
        unsigned idx = node.getId();
        if (! (idx < d.size() ) )
            d.resize(2*idx, IStreamDetails(0,0,0,0));
        d[node.getId()] = IStreamDetails(line, pos, start, end);
    }
    unsigned int getLine(PDTNode & n) const {
        return d[n.getId()].line;
    }
    unsigned int getLinePos(PDTNode & n) const {
        return d[n.getId()].pos;
    }
    unsigned int getStart(PDTNode & n) const {
        return d[n.getId()].start;
    }
    unsigned int getEnd(PDTNode & n) const {
        return d[n.getId()].end;
    }
#endif
	void updateCurrentId();

	PDTCodeGraph();
	void addNode(PDTNode * node);
	void addVar(PDTVar * var);
	void addConst(PDTConst * cons);
	void addProp(PDTProp * prop);
	NodeTypeEnum getType() {return PDTCodeGraph_Em;}
	void traverse(PDTNode * node);

    PDTFunctionDec * findFunction(const string &funcName);

	PDTNode* findPreCG(string preName,unsigned int i=0);
	PDTNode* findPostCG(string postName, unsigned int i=0);
	PDTNode* findBehaviorCG(string behaviorName, unsigned int i=0);

	PDTNode* findFunctionCall(string funcName);
	PDTNode* findVariable(string varName);
	void printAllVariables();
};

#endif
